#ifndef __FD_REACTOR_H__
#define __FD_REACTOR_H__

#include <map>
#include <vector>
#include <atomic>

#include <utility>
#include <memory>
#include <functional>
#include <mutex>
#include <thread>

#include <sys/epoll.h>

#include "fd_context.h"
#include "../co.h"
#include "../common/semaphore.h"
#include "../common/record_counter.h"

const int MAX_SLOT_COUNT = 128;

struct CoFdInfo;
struct CoFdCidInfo;

typedef std::shared_ptr<CoFdContext> FdContextPtr;
typedef std::weak_ptr<CoFdContext> FdContextWPtr;

struct CoFdCidInfo
{
	short* revents;
	CoSuspendEntry entry;
};

struct CoReactorFdInfo
{
    FdContextPtr ptr;
    std::map<int, CoFdCidInfo> r_cid_infos;
    std::map<int, CoFdCidInfo> w_cid_infos;
};

struct CoReactorSlotInfo
{
    std::mutex mu;
    std::map<int, CoReactorFdInfo> fd_infos;
};

struct CoReactorInfo
{
    int epoll_id;
    int notify_fds[2];

    std::vector<std::shared_ptr<CoReactorSlotInfo>> slots;
};


class CoFdReactor : public LogAdapterCo<CoFdReactor>
{
public:
	CoFdReactor();
	~CoFdReactor();

	bool init();
	
	void stop();

    bool is_exist(FdContextPtr ptr);

	bool set(FdContextPtr ptr, short events, short* revents, const CoSuspendEntry& entry);

    bool detach(FdContextPtr ptr, std::function<void (FdContextPtr& ptr, bool is_release)> func = nullptr);

	CoFdReactorCounter get_counter_statics();

private:
	void run(int index);

	void handle_event(int index, int fd, int events);

public:
    RecordCounter<CoFdReactorCounter> _counter;

private:
	std::vector<std::thread> _threads;

    std::vector<std::shared_ptr<CoReactorInfo>> _reactor_infos;
};

#endif

